{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "3652aca5-46be-454d-9b5e-5b795379c534",
   "metadata": {},
   "source": [
    "# Modeling an HHL Algorithm to Solve a Set of Linear Equations"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "422c4e26-b10c-4d77-b7ea-5d06d684a752",
   "metadata": {},
   "source": [
    "Solving linear equations appears in many research, engineering, and design fields. For example, many physical and financial models, from fluid dynamics to portfolio optimization, are described by partial differential equations, which are typically treated by numerical schemes, most of which are eventually transformed to a set of linear equations.\n",
    "\n",
    "The HHL algorithm [[1](#HHL)] is a quantum algorithm for solving a set of linear equations. It is one of the fundamental quantum algorithms that is expected to give a speedup over its classical counterpart.\n",
    "\n",
    "\n",
    "A set of linear equations of size $N$ is represented by an $N\\times N$ matrix and a vector $b$ of size $N$,\n",
    "$$\n",
    "A\\vec{x} = \\vec{b},\n",
    "$$\n",
    "where the solution to the problem is designated by the solution variable $\\vec{x}$.\n",
    "\n",
    "For simplicity, the demo below treats a usecase where $\\vec{b}$ is a normalized vector $|\\vec{b}|=1$, and $A$ is an Hermitian matrix of size $2^n\\times 2^n$, whose eigenvalues are in the interval $(0,1)$. Generalizations to other usecases are discussed at the end of this demo."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2fcf999-36cf-4536-9661-bd69c254a198",
   "metadata": {
    "tags": []
   },
   "source": [
    "## 1. Defining a Specific Problem"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb8942f5-23a0-4370-b83b-d6c41f6af033",
   "metadata": {},
   "source": [
    "Start by defining the specific problem."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "be9d807b-7536-4968-8a18-397f69763964",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:31.377456Z",
     "iopub.status.busy": "2024-05-07T14:33:31.375871Z",
     "iopub.status.idle": "2024-05-07T14:33:31.518329Z",
     "shell.execute_reply": "2024-05-07T14:33:31.517547Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A = [[ 0.28 -0.01  0.02 -0.1 ]\n",
      " [-0.01  0.5  -0.22 -0.07]\n",
      " [ 0.02 -0.22  0.43 -0.05]\n",
      " [-0.1  -0.07 -0.05  0.42]] \n",
      "\n",
      "b = [0.18257419 0.36514837 0.73029674 0.54772256]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "A = np.array(\n",
    "    [\n",
    "        [0.28, -0.01, 0.02, -0.1],\n",
    "        [-0.01, 0.5, -0.22, -0.07],\n",
    "        [0.02, -0.22, 0.43, -0.05],\n",
    "        [-0.1, -0.07, -0.05, 0.42],\n",
    "    ]\n",
    ")\n",
    "\n",
    "b = np.array([1, 2, 4, 3])\n",
    "b = b / np.linalg.norm(b)\n",
    "\n",
    "print(\"A =\", A, \"\\n\")\n",
    "print(\"b =\", b)\n",
    "\n",
    "# verifying that the matrix is symmetric and has eigenvalues in [0,1)\n",
    "if not np.allclose(A, A.T, rtol=1e-6, atol=1e-6):\n",
    "    raise Exception(\"The matrix is not symmetric\")\n",
    "w, v = np.linalg.eig(A)\n",
    "for lam in w:\n",
    "    if lam < 0 or lam > 1:\n",
    "        raise Exception(\"Eigenvalues are not in (0,1)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1bd14c32-152e-486c-afdf-cdb5e4658c75",
   "metadata": {},
   "source": [
    "## 2. Defining Quantum and Classical Functions\n",
    "\n",
    "The quantum program below has to encode the unitary matrix $U=e^{iA}$. For this, you have to decompose the matrix $A$ into a sum of Pauli strings. This is a completely classical pre-processing that can be done with a naive decomposition. More efficient decompositions can be devised. Another classical function which allows to move from a list of Pauli strings and coefficients to `PauliTerm` type is also useful.\n",
    "\n",
    "In addition, it will be essential to work with a flexible-QPE function, which allows a flexible and efficient implementation of this function block."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "041542a8-0ffc-426c-820f-91f1e93a0d49",
   "metadata": {},
   "source": [
    "### 2.1 Pauli Decomposition\n",
    "\n",
    "Define the `lcu_naive` auxiliary function for the classical pre-processing: decomposing a matrix into the sum of Pauli strings."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "9f725a02-85db-42a9-8d3c-807ff4455ca7",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:31.524508Z",
     "iopub.status.busy": "2024-05-07T14:33:31.523231Z",
     "iopub.status.idle": "2024-05-07T14:33:31.535879Z",
     "shell.execute_reply": "2024-05-07T14:33:31.535168Z"
    }
   },
   "outputs": [],
   "source": [
    "from itertools import product\n",
    "\n",
    "from numpy import kron\n",
    "\n",
    "Paulidict = {\n",
    "    \"I\": np.array([[1, 0], [0, 1]], dtype=np.complex128),\n",
    "    \"Z\": np.array([[1, 0], [0, -1]], dtype=np.complex128),\n",
    "    \"X\": np.array([[0, 1], [1, 0]], dtype=np.complex128),\n",
    "    \"Y\": np.array([[0, -1j], [1j, 0]], dtype=np.complex128),\n",
    "}\n",
    "\n",
    "\n",
    "# generate all combinations of Pauli strings of size n\n",
    "def generate_all_pauli_strings(seq, n):\n",
    "    for s in product(seq, repeat=n):\n",
    "        yield \"\".join(s)\n",
    "\n",
    "\n",
    "# convert a Paulistring of size n to 2**n X 2**n matrix\n",
    "def pauli_string_2mat(seq):\n",
    "    myPmat = Paulidict[seq[0]]\n",
    "    for p in seq[1:]:\n",
    "        myPmat = kron(myPmat, Paulidict[p])\n",
    "    return myPmat\n",
    "\n",
    "\n",
    "# Hilbert-Schmidt-Product of two matrices M1, M2\n",
    "def hilbert_schmidt(M1, M2):\n",
    "    return (np.dot(M1.conjugate().transpose(), M2)).trace()\n",
    "\n",
    "\n",
    "# Naive decomposition, running over all HS products for all Pauli strings\n",
    "def lcu_naive(H):\n",
    "    assert H.shape[0] == H.shape[1], \"matrix is not square\"\n",
    "    assert H.shape[0] != 0, \"matrix is of size 0\"\n",
    "    assert H.shape[0] & (H.shape[0] - 1) == 0, \"matrix size is not 2**n\"\n",
    "\n",
    "    n = int(np.log2(H.shape[0]))\n",
    "    myPualiList = list(generate_all_pauli_strings(\"IZXY\", n))\n",
    "\n",
    "    mylist = []\n",
    "\n",
    "    for pstr in myPualiList:\n",
    "        co = (1 / 2**n) * hilbert_schmidt(pauli_string_2mat(pstr), H)\n",
    "        if co != 0:\n",
    "            mylist = mylist + [(pstr, co)]\n",
    "\n",
    "    return mylist"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "07a1748b-8505-4b99-9d59-e74ad2ad25fe",
   "metadata": {},
   "source": [
    "### 2.2 Parser to the `PauliTerm` struct\n",
    "\n",
    "Define the `pauli_operator_to_hamiltonian` auxiliary function that takes a list of Pauli strings and coefficients, and returns the corresponding struct to be entered into the Hamiltonian dynamics."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "fc51edcb-f318-4b44-b43a-d5d545ca0a09",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:31.540970Z",
     "iopub.status.busy": "2024-05-07T14:33:31.539725Z",
     "iopub.status.idle": "2024-05-07T14:33:34.217642Z",
     "shell.execute_reply": "2024-05-07T14:33:34.216955Z"
    }
   },
   "outputs": [],
   "source": [
    "from typing import cast\n",
    "\n",
    "from classiq import Pauli, PauliTerm\n",
    "\n",
    "my_list = {\"I\": Pauli.I, \"X\": Pauli.X, \"Y\": Pauli.Y, \"Z\": Pauli.Z}\n",
    "\n",
    "\n",
    "def pauli_str_to_enums(pauli):\n",
    "    return [my_list[s] for s in pauli]\n",
    "\n",
    "\n",
    "def pauli_operator_to_hamiltonian(pauli_list):\n",
    "    return [\n",
    "        PauliTerm(\n",
    "            pauli=pauli_str_to_enums(pauli), coefficient=cast(complex, coeff).real\n",
    "        )\n",
    "        for pauli, coeff in pauli_list\n",
    "    ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "09ca56d2-3618-4640-97c4-4d23efef7d86",
   "metadata": {},
   "source": [
    "### 2.3 A Matrix Inversion Function with Flexible QPE\n",
    "\n",
    "Define a quantum matrix inversion function `my_matrix_inversion_flexible`, which gets a unitary operand to implement $e^{iA}$, a `precision` integer for the eigenvalues, and a quantum variable `state` for the $|\\vec{b}\\rangle$ vector. The function returns the normalized solution:\n",
    "$$\n",
    "C |A^{-1}\\vec{b}||A^{-1}\\vec{b}\\rangle|1\\rangle + \\tilde{C} |{\\rm garbage}\\rangle|0\\rangle,\n",
    "$$\n",
    "where $\\tilde{C}$ and $|{\\rm garbage}\\rangle$ are irrelevant quantities, as the solution is entangled with the `indicator` output qubit at state $|1\\rangle$.\n",
    "The normalization coefficient $C$, which guarantees that the amplitudes are normalized, can be taken as the lower possible eigenvalue that can be resolved with the QPE:\n",
    "$$\n",
    "C=1/2^{\\rm precision}.\n",
    "$$\n",
    "\n",
    "Comments:\n",
    "* Use the built-in `qpe_flexible` function, see [Flexible QPE tutorial](https://docs.classiq.io/latest/tutorials/tutorials/high-level-modeling-flexible-qpe/high-level-modeling-flexible-qpe/ ).\n",
    "* The built-in construct to define an amplitude loading is designated by `*=`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "613bc2e0-d11a-4a75-89c5-5cb9ea30a62a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:34.220829Z",
     "iopub.status.busy": "2024-05-07T14:33:34.220160Z",
     "iopub.status.idle": "2024-05-07T14:33:34.225628Z",
     "shell.execute_reply": "2024-05-07T14:33:34.225029Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import (\n",
    "    CInt,\n",
    "    Output,\n",
    "    QArray,\n",
    "    QBit,\n",
    "    QCallable,\n",
    "    QNum,\n",
    "    allocate,\n",
    "    allocate_num,\n",
    "    qfunc,\n",
    "    qpe_flexible,\n",
    "    within_apply,\n",
    ")\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def simple_eig_inv(phase: QNum, indicator: Output[QBit]):\n",
    "    allocate(1, indicator)\n",
    "    indicator *= (1 / 2**phase.size) / phase\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def my_matrix_inversion_flexible(\n",
    "    unitary_with_power: QCallable[CInt, QArray[QBit]],\n",
    "    precision: CInt,\n",
    "    state: QArray[QBit],\n",
    "    indicator: Output[QBit],\n",
    ") -> None:\n",
    "    phase = QNum(\"phase\")\n",
    "    allocate_num(precision, False, precision, phase)\n",
    "    within_apply(\n",
    "        lambda: qpe_flexible(\n",
    "            unitary_with_power=lambda k: unitary_with_power(k, state), phase=phase\n",
    "        ),\n",
    "        lambda: simple_eig_inv(phase=phase, indicator=indicator),\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3428f607-76cd-497c-a702-1fcf9be2fd4a",
   "metadata": {},
   "source": [
    "## 3. Modelling an HHL Algorithm"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f7a2b7f9-1624-475f-9115-52a1bffc1083",
   "metadata": {},
   "source": [
    "This tutorial gives instructions on building an HHL algorithm and presents the theory of the algorithm. The algorithm consists of 4 steps:\n",
    "1) State preparation of the RHS vector $\\vec{b}$.\n",
    "2) QPE for the unitary matrix $e^{2\\pi iA}$, which encodes eigenvalues on a quantum register of size $m$.\n",
    "3) An inversion algorithm that loads amplitudes according to the inverse of the eigenvalue registers.\n",
    "4) An inverse QPE with the parameters in (2)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76002419-2daf-4991-b8a4-ecf9f70a0fb5",
   "metadata": {
    "tags": []
   },
   "source": [
    "### 3.1 State Preparation for the Vector $\\vec{b}$\n",
    "\n",
    "The first stage of the HHL algorithm is to load the normalized RHS vector $\\vec{b}$ into a quantum register:\n",
    "$$\n",
    "|0\\rangle_n \\xrightarrow[{\\rm SP}]{} \\sum^{2^n-1}_{i=0}b_i|i\\rangle_n\n",
    "$$\n",
    "where $|i\\rangle$ are states in the computational basis.\n",
    "\n",
    "**The relevant built-in function is the `prepare_amplitudes` one, which gets $2^n$ values of $\\vec{b}$, as well as an upper bound for its functional error through the `bound` parameter.**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2ebd773d-b5e5-40c8-97e5-95a22188b472",
   "metadata": {
    "lines_to_next_cell": 0,
    "tags": []
   },
   "source": [
    "### 3.2 Quantum Phase Estimation (QPE) for the Hamiltonian Evolution $U=e^{2\\pi i A }$\n",
    "\n",
    "The QPE function block, which is at the heart of the HHL algorithm, operates as follows: Unitary matrices have eigenvalues of norm 1, and thus are of the form $e^{2\\pi i \\lambda}$, with $0\\leq\\lambda<1$. For a quantum state $|\\psi\\rangle_n$, prepared in an eigenvalue of some unitary matrix $U$ of size $2^n\\times 2^n$, the QPE algorithm encodes the corresponding  eigenvalue into a quantum register:\n",
    "$$\n",
    "|0\\rangle_m|\\psi\\rangle_n \\xrightarrow[{\\rm QPE}(U)]{} |\\lambda\\rangle_m|\\psi\\rangle_n,\n",
    "$$\n",
    "where $m$ is the precision of the binary representation of $\\lambda$, $\\lambda=\\frac{1}{2^m}\\sum^{2^m-1}_{k=0}\\lambda^{(k)}2^k$ with $\\lambda^{(k)}$ being the state of the $k$-th qubit.\n",
    "\n",
    "In the HHL algorithm a QPE for the unitary $U=e^{2\\pi i A }$ is applied. The mathematics: First, note that the eigenvectors of $U$ are the ones of the matrix $A$, and that the corresponding eigenvalues $\\lambda$ defined for $U=e^{2\\pi i A }$ are the eigenvalues of $A$. Second, represent the prepared state in the basis given by the eigenvalues of $A$. This is merely a mathematical transformation; with no algorithmic considerations here. If the eigenbasis of $A$ is given by the set $\\{|\\psi_j\\rangle_n \\}^{2^n-1}_{j=0}$, then\n",
    "$$\n",
    "\\sum^{2^n-1}_{i=0}b_i|i\\rangle_n = \\sum^{2^n-1}_{j=0}\\beta_j|\\psi_j\\rangle_n.\n",
    "$$\n",
    "Applying the QPE stage gives\n",
    "$$\n",
    "|0\\rangle_m \\sum^{2^n-1}_{j=0}\\beta_j|\\psi_j\\rangle_n \\xrightarrow[{\\rm QPE}]{}  \\sum^{2^n-1}_{j=0}\\beta_j |\\lambda_j\\rangle_m |\\psi_j\\rangle_n.\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ffcbdfd-6c23-47ad-8955-ec8fd0861e32",
   "metadata": {
    "lines_to_next_cell": 0,
    "tags": []
   },
   "source": [
    "For the QPE you are going to use Classiq's `suzuki-trotter` function of order 1 for Hamiltonian evolution $e^{-i H t}$. This function is an approximated one, where its `repetitions` parameter controls its error. For a QPE algorithm with size $m$ a series of controlled-unitaries $U^{2^s}$ $0 \\leq s \\leq m-1$ are applied, for each of which we would like to pass a different `repetitions` parameter depth (to keep a roughly same error, the repetitions for approximating $U=e^{2\\pi i 2^s A }$ is expected to be $\\sim 2^s$ larger then the repetitions of $U=e^{2\\pi i A }$). In Classiq this can be done by working with a flexiable-QPE, and passing a \"rule\" for how to exponentiate each step within the QPE."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eabb4c09-3748-4452-8e01-f33201403d24",
   "metadata": {},
   "source": [
    "#### 3.2.1 Defining a Powered Hamiltonian Evolution\n",
    "\n",
    "Define the inner quantum  call to be used within the flexible QPE: a Suzuki Trotter of order 1, whose repetitions parameter grows by some constant factor proportional to the evolution coefficient. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "0ffb2c3e-2a54-4b35-9554-03f2c719f017",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:34.228168Z",
     "iopub.status.busy": "2024-05-07T14:33:34.227894Z",
     "iopub.status.idle": "2024-05-07T14:33:34.231756Z",
     "shell.execute_reply": "2024-05-07T14:33:34.231167Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import CArray, CReal, suzuki_trotter\n",
    "from classiq.qmod.symbolic import ceiling, log\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def suzuki_trotter1_with_power_logic(\n",
    "    hamiltonian: CArray[PauliTerm],\n",
    "    pw: CInt,\n",
    "    r0: CInt,\n",
    "    reps_scaling_factor: CReal,\n",
    "    evolution_coefficient: CReal,\n",
    "    target: QArray[QBit],\n",
    ") -> None:\n",
    "    suzuki_trotter(\n",
    "        hamiltonian,\n",
    "        evolution_coefficient=evolution_coefficient * pw,\n",
    "        order=1,\n",
    "        repetitions=r0 * ceiling(reps_scaling_factor ** (log(pw, 2))),\n",
    "        qbv=target,\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f96299ef-f5a2-43db-8afa-ce5d1a42cbe8",
   "metadata": {
    "tags": []
   },
   "source": [
    "### 3.3 Eigenvalue Inversion\n",
    "\n",
    "The next step in the HHL algorithm is to pass the inverse of the eigenvalue registers into their amplitudes, using the Amplitude Loading (AL) construct.\n",
    "Given a function $f:[0,1)\\rightarrow [-1,1]$, it implements $|0\\rangle|\\lambda\\rangle_m \\xrightarrow[{\\rm AL}(f)]{} f(\\lambda)|1\\rangle|\\lambda\\rangle_m+\\sqrt{1-f^2(\\lambda)}|0\\rangle|\\lambda\\rangle_m$. For the HHL algorithm, apply an AL with $f=C/x$ where $C$ is a lower bound for the minimal eigenvalue of $A$.\n",
    "Applying this AL gives\n",
    "$$\n",
    "\\sum^{2^n-1}_{j=0}\\beta_j |\\lambda_j\\rangle_m |\\psi_j\\rangle_n \\xrightarrow[{\\rm AL}(C/x)]{}\n",
    "|0\\rangle\\left(\\sum^{2^n-1}_{j=0}\\sqrt{1-\\frac{C^2}{\\lambda^2_j}}\\beta_j |\\lambda_j\\rangle_m |\\psi_j\\rangle_n\\right)+\n",
    "|1\\rangle\\left(\\sum^{2^n-1}_{j=0}\\frac{C}{\\lambda_j}\\beta_j |\\lambda_j\\rangle_m |\\psi_j\\rangle_n\\right),\n",
    "$$\n",
    "\n",
    "\n",
    "where $C$ is a normalization coefficient."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a236d715-b9da-46f8-aaee-b085506d0ddc",
   "metadata": {
    "tags": []
   },
   "source": [
    "### 3.4 Inverse QPE\n",
    "\n",
    "As the final step in the HHL model, clean the QPE register by applying an inverse-QPE. (Note that it is not guaranteed that this register is completely cleaned; namely, that all the qubits in the QPE register return to zero after the inverse-QPE. Generically they are all zero with very high probability).\n",
    "\n",
    "In this model we will simply call the QPE function with the same parameters in stage 2. This is how the quantum state looks now\n",
    "$$\n",
    " |0\\rangle\\left(\\sum^{2^n-1}_{j=0}\\sqrt{1-\\frac{C^2}{\\lambda^2_j}}\\beta_j |\\lambda_j\\rangle_m |\\psi_j\\rangle_n\\right)+\n",
    "|1\\rangle\\left(\\sum^{2^n-1}_{j=0}\\frac{C}{\\lambda_j}\\beta_j |\\lambda_j\\rangle_m |\\psi_j\\rangle_n\\right)\n",
    "\\xrightarrow[{\\rm inv-QPE}(U)]{}\n",
    " |0\\rangle_m|0\\rangle\\left(\\sum^{2^n-1}_{j=0}\\sqrt{1-\\frac{C^2}{\\lambda^2_j}}\\beta_j  |\\psi_j\\rangle_n\\right)+\n",
    "|0\\rangle_m|1\\rangle\\left(\\sum^{2^n-1}_{j=0}\\frac{C}{\\lambda_j}\\beta_j  |\\psi_j\\rangle_n\\right)\n",
    "$$\n",
    "\n",
    "The state entangled with $|1\\rangle$ stores the solution to our problem (up to some normalization problem)\n",
    "$$\n",
    "\\sum^{2^n-1}_{j=0} \\frac{C}{\\lambda_j}\\beta_j  \\vec{\\psi_j} = C\\vec{x}.\n",
    "$$\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1cb6cf24-55aa-4e9e-9e69-bad14f95f8cf",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "\n",
    "**In this notebook, steps 3.2-3.4 are encapsulated into a single user defined quantum function, `my_matrix_inversion_flexible`, defined in Sec. (2.4)**\n",
    "\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57fd9798-8faf-4f58-8d5d-5453482b9d8c",
   "metadata": {},
   "source": [
    "### 3.5 The HHL Model"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ae73619e-ca62-4a45-9bb9-1ebeec4d0a2c",
   "metadata": {},
   "source": [
    "First, use the auxiliary function to decompose the matrix $A$ for the specific usecase. The variable `paulis` holds the list of Pauli strings that represents our matrix. The number of qubits to represent the matrix is stored in the variable `n`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "b8c404c7-cabb-4fbc-bdb7-497f03d04c84",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:34.234300Z",
     "iopub.status.busy": "2024-05-07T14:33:34.233942Z",
     "iopub.status.idle": "2024-05-07T14:33:34.239508Z",
     "shell.execute_reply": "2024-05-07T14:33:34.238850Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Pauli strings list: \n",
      "\n",
      "II :  (0.408+0j)\n",
      "IZ :  (-0.052+0j)\n",
      "IX :  (-0.03+0j)\n",
      "ZI :  (-0.017+0j)\n",
      "ZZ :  (-0.057+0j)\n",
      "ZX :  (0.02+0j)\n",
      "XI :  (-0.025+0j)\n",
      "XZ :  (0.045+0j)\n",
      "XX :  (-0.16+0j)\n",
      "YY :  (-0.06+0j)\n",
      "\n",
      " Number of qubits for matrix representation = 2\n"
     ]
    }
   ],
   "source": [
    "paulis = lcu_naive(A)\n",
    "n = len(paulis[0][0])\n",
    "print(\"Pauli strings list: \\n\")\n",
    "for p in paulis:\n",
    "    print(p[0], \": \", np.round(p[1], 3))\n",
    "\n",
    "print(\"\\n Number of qubits for matrix representation =\", n)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "15a099c2-ee1d-4ee3-8561-0b117e6ebe44",
   "metadata": {},
   "source": [
    "Build the quantum model calling the four quantum functions described above:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "8a55813c-e4e8-4490-92a0-90816ad220d2",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:34.241735Z",
     "iopub.status.busy": "2024-05-07T14:33:34.241559Z",
     "iopub.status.idle": "2024-05-07T14:33:34.246229Z",
     "shell.execute_reply": "2024-05-07T14:33:34.245639Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import Output, create_model, prepare_amplitudes, synthesize\n",
    "from classiq.qmod.symbolic import floor\n",
    "\n",
    "# parameters for the amplitude preparation\n",
    "amplitudes = b.tolist()\n",
    "SP_ERROR = 0.0\n",
    "# parameters for the QPE\n",
    "QPE_SIZE = 4\n",
    "R0 = 4\n",
    "REPS_SCALING_FACTOR = 1.8\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def main(\n",
    "    res: Output[QArray[QBit, floor(log(len(amplitudes), 2))]],\n",
    "    indicator: Output[QBit],\n",
    ") -> None:\n",
    "    prepare_amplitudes(amplitudes, SP_ERROR, res)\n",
    "    my_matrix_inversion_flexible(\n",
    "        unitary_with_power=lambda pw, target: suzuki_trotter1_with_power_logic(\n",
    "            hamiltonian=pauli_operator_to_hamiltonian(paulis),\n",
    "            pw=pw,\n",
    "            evolution_coefficient=-2 * np.pi,\n",
    "            r0=R0,\n",
    "            reps_scaling_factor=REPS_SCALING_FACTOR,\n",
    "            target=target,\n",
    "        ),\n",
    "        precision=QPE_SIZE,\n",
    "        state=res,\n",
    "        indicator=indicator,\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a9012395-5cbf-43b2-8c1a-46f09deff431",
   "metadata": {},
   "source": [
    "This tutorial compares the classical and quantum solutions, so execute the resulting circuit on a statevector simulator. To define this part of the model, set `Sample` and `ExecutionPreferences` of a statevector simulator."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "7cb726cf-05b7-4cde-b906-f2a65002ec55",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:34.248551Z",
     "iopub.status.busy": "2024-05-07T14:33:34.248245Z",
     "iopub.status.idle": "2024-05-07T14:33:34.283984Z",
     "shell.execute_reply": "2024-05-07T14:33:34.283313Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq.execution import (\n",
    "    ClassiqBackendPreferences,\n",
    "    ClassiqSimulatorBackendNames,\n",
    "    ExecutionPreferences,\n",
    ")\n",
    "from classiq.synthesis import set_execution_preferences\n",
    "\n",
    "backend_preferences = ClassiqBackendPreferences(\n",
    "    backend_name=ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR\n",
    ")\n",
    "qmod_hhl = create_model(main)\n",
    "\n",
    "qmod_hhl = set_execution_preferences(\n",
    "    qmod_hhl,\n",
    "    execution_preferences=ExecutionPreferences(\n",
    "        num_shots=1, backend_preferences=backend_preferences\n",
    "    ),\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "cc3ba894-8a73-4891-ad55-6f22fa3fdfb5",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:34.286734Z",
     "iopub.status.busy": "2024-05-07T14:33:34.286225Z",
     "iopub.status.idle": "2024-05-07T14:33:34.301804Z",
     "shell.execute_reply": "2024-05-07T14:33:34.301165Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import write_qmod\n",
    "\n",
    "write_qmod(qmod_hhl, \"hhl\", decimal_precision=10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e0caed5-950c-43f8-90cf-d841731b4ea5",
   "metadata": {},
   "source": [
    "#### 3.5.1 Synthesizing the Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "f0ffc6b8-cdb8-468b-932f-89942c639b5d",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:34.304456Z",
     "iopub.status.busy": "2024-05-07T14:33:34.304056Z",
     "iopub.status.idle": "2024-05-07T14:33:48.011977Z",
     "shell.execute_reply": "2024-05-07T14:33:48.011337Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import synthesize\n",
    "\n",
    "qprog_hhl = synthesize(qmod_hhl)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "92eceedd-b8df-42ef-85cc-cddde8deedc2",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:48.014786Z",
     "iopub.status.busy": "2024-05-07T14:33:48.014326Z",
     "iopub.status.idle": "2024-05-07T14:33:48.095960Z",
     "shell.execute_reply": "2024-05-07T14:33:48.095280Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Opening: https://platform.classiq.io/circuit/7afdfd36-aab3-4ee7-9f85-9e98810aaea8?version=0.41.0.dev39%2B79c8fd0855\n"
     ]
    }
   ],
   "source": [
    "from classiq import show\n",
    "\n",
    "show(qprog_hhl)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "8a95d759-793d-4351-a57e-8fec86145413",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:48.098587Z",
     "iopub.status.busy": "2024-05-07T14:33:48.098145Z",
     "iopub.status.idle": "2024-05-07T14:33:48.112100Z",
     "shell.execute_reply": "2024-05-07T14:33:48.111478Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "depth =  5074\n"
     ]
    }
   ],
   "source": [
    "from classiq import QuantumProgram\n",
    "\n",
    "circuit_hhl = QuantumProgram.from_qprog(qprog_hhl)\n",
    "print(\"depth = \", circuit_hhl.transpiled_circuit.depth)"
   ]
  },
  {
   "attachments": {
    "Screen%20Shot%202023-01-25%20at%2014.27.58.png": {
     "image/png": "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"
    }
   },
   "cell_type": "markdown",
   "id": "a34e1ae9-168c-4d1c-a3f1-2d1f56bc78c6",
   "metadata": {},
   "source": [
    "![Screen%20Shot%202023-01-25%20at%2014.27.58.png](attachment:Screen%20Shot%202023-01-25%20at%2014.27.58.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73bbb2d9-ea89-4b00-b4b9-40689c11a565",
   "metadata": {},
   "source": [
    "### 3.6 Executing and Verifying the Result Via the Statevector Simulator\n",
    "\n",
    "Execute the quantum program. Recall that you chose a statevector simulator because you want the exact solution."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "14bc85cb-1000-4e2d-b96f-a0c324c60b27",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:48.114717Z",
     "iopub.status.busy": "2024-05-07T14:33:48.114262Z",
     "iopub.status.idle": "2024-05-07T14:33:52.470870Z",
     "shell.execute_reply": "2024-05-07T14:33:52.470247Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import execute\n",
    "\n",
    "results = execute(qprog_hhl).result()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "18b30c40-7d6f-4b72-86a0-b9c3fd1ed5f6",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:52.473553Z",
     "iopub.status.busy": "2024-05-07T14:33:52.473187Z",
     "iopub.status.idle": "2024-05-07T14:33:52.476194Z",
     "shell.execute_reply": "2024-05-07T14:33:52.475615Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq.execution import ExecutionDetails\n",
    "\n",
    "res_hhl = results[0].value"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f43da2d4-8859-4abe-a2a4-d9ccb135ca4e",
   "metadata": {},
   "source": [
    "Read the specific results given in the `res` register defined in the model, caring only for entries where the target register is 1."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "4a3ae809-d511-4f33-850e-ea50d6e4fab4",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:52.478608Z",
     "iopub.status.busy": "2024-05-07T14:33:52.478253Z",
     "iopub.status.idle": "2024-05-07T14:33:52.481082Z",
     "shell.execute_reply": "2024-05-07T14:33:52.480516Z"
    },
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "total_q = circuit_hhl.data.width  # total number of qubits of the whole circuit"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ec5d598-de3d-44b1-866c-39490350f79f",
   "metadata": {},
   "source": [
    "Read the qubit allocation of the relevant registers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "648879af-eda8-4259-9f7e-006d126872c6",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:52.483477Z",
     "iopub.status.busy": "2024-05-07T14:33:52.483044Z",
     "iopub.status.idle": "2024-05-07T14:33:52.486588Z",
     "shell.execute_reply": "2024-05-07T14:33:52.486002Z"
    }
   },
   "outputs": [],
   "source": [
    "target_pos = res_hhl.physical_qubits_map[\"indicator\"][0]  # position of control qubit\n",
    "\n",
    "sol_pos = list(res_hhl.physical_qubits_map[\"res\"])  # position of solution\n",
    "\n",
    "phase_pos = [\n",
    "    total_q - k - 1 for k in range(total_q) if k not in sol_pos + [target_pos]\n",
    "]  # Finds the position of the \u201cphase\u201d register and flips for endianness, as you will use the indices to read directly from the string"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f520a242-c0d8-49b9-94d1-750da0555fb2",
   "metadata": {},
   "source": [
    "Define a run over all the relevant strings holding the solution. The solution vector will be inserted into the variable `qsol`. Factor out $C=1/2^m$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "b8b5ed43-3618-44a0-b0a5-f632c0caef15",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:52.489103Z",
     "iopub.status.busy": "2024-05-07T14:33:52.488613Z",
     "iopub.status.idle": "2024-05-07T14:33:52.505761Z",
     "shell.execute_reply": "2024-05-07T14:33:52.505131Z"
    }
   },
   "outputs": [],
   "source": [
    "qsol = [\n",
    "    np.round(parsed_state.amplitude / (1 / 2**QPE_SIZE), 5)\n",
    "    for solution in range(2**n)\n",
    "    for parsed_state in res_hhl.parsed_state_vector\n",
    "    if parsed_state[\"indicator\"] == 1.0\n",
    "    and parsed_state[\"res\"] == solution\n",
    "    and [parsed_state.bitstring[k] for k in phase_pos]\n",
    "    == [\"0\"]\n",
    "    * QPE_SIZE  # this takes the entries where the \u201cphase\u201d register is at state zero\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "007beff5-5fd8-48cf-a4bc-625afa655456",
   "metadata": {},
   "source": [
    "#### 3.6.1 Comparing classical and quantum solutions.\n",
    "\n",
    "Note that the HHL algorithm returns a statevector result up to some global phase (coming from transpilation or from the quantum functions themselves). Therefore, to compare with the classical solution, correct for this global phase."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "042ef3f0-5c07-4354-99e5-7809bd1ce51f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:52.508366Z",
     "iopub.status.busy": "2024-05-07T14:33:52.507974Z",
     "iopub.status.idle": "2024-05-07T14:33:52.513002Z",
     "shell.execute_reply": "2024-05-07T14:33:52.512315Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "classical:   [1.3814374  2.50585064 3.19890483 2.43147877]\n",
      "HHL:         [1.4399586  2.57143349 3.26031736 2.45618776]\n",
      "relative distance:   2.2 %\n"
     ]
    }
   ],
   "source": [
    "sol_classical = np.linalg.solve(A, b)\n",
    "global_phase = np.angle(qsol)\n",
    "qsol_corrected = np.real(qsol / np.exp(1j * global_phase))\n",
    "print(\"classical:  \", sol_classical)\n",
    "print(\"HHL:        \", qsol_corrected)\n",
    "print(\n",
    "    \"relative distance:  \",\n",
    "    round(\n",
    "        np.linalg.norm(sol_classical - qsol_corrected)\n",
    "        / np.linalg.norm(sol_classical)\n",
    "        * 100,\n",
    "        1,\n",
    "    ),\n",
    "    \"%\",\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "34b41fea-01e9-43b5-b943-c36f9da6ac73",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:52.515494Z",
     "iopub.status.busy": "2024-05-07T14:33:52.514959Z",
     "iopub.status.idle": "2024-05-07T14:33:52.765202Z",
     "shell.execute_reply": "2024-05-07T14:33:52.764426Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAGxCAYAAACKvAkXAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuNSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/xnp5ZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAzRElEQVR4nO3de3QUVYLH8V8TSYdH0oCQl2kgCgblPQgYFEGNBHWUyDoK4whxUGcwzJHFxxpXRVfdIL7AWQ6MD8iqA7gIwVlUHgKJIAEFiQIqCoZ3Ag4r3RAlYOfuH5n02CTBhKS7OtT3c06dWLduVW5V2u4fVbfvdRhjjAAAAGykmdUNAAAACDUCEAAAsB0CEAAAsB0CEAAAsB0CEAAAsB0CEAAAsB0CEAAAsJ1zrG5AOKqoqNCBAwcUHR0th8NhdXMAAEAdGGN09OhRJSYmqlmz09/jIQDV4MCBA3K73VY3AwAAnIG9e/cqKSnptHUIQDWIjo6WVHkBY2JiLG4NAACoC6/XK7fb7f8cPx0CUA2qHnvFxMQQgAAAaGLq0n2FTtAAAMB2CEAAAMB2CEAAAMB26AMEAMA/+Hw+nTx50upm4DQiIyN/8SvudUEAAgDYnjFGpaWlOnLkiNVNwS9o1qyZkpOTFRkZ2aDjEIAAALZXFX5iY2PVsmVLBsENU1UDFZeUlKhjx44N+jsRgAAAtubz+fzh59xzz7W6OfgFHTp00IEDB/TTTz+pefPmZ3wcOkEDAGytqs9Py5YtLW4J6qLq0ZfP52vQcQhAAACoboPnwXqN9XfiERgAoGY+n7RmjVRSIiUkSIMHSxERVrcKaBQEIABAdYsWSffeK+3b98+ypCRp+nRp5Ejr2gU0Eh6BAQACLVok3XxzYPiRpP37K8sXLbKmXU2Azyfl50vz5lX+bGA3lTO2a9cuORwOFRUVBf135ebmqk2bNo12vPz8fDkcjqAPSWBpAJo5c6Z69erln3Q0NTVV77//fq31X3nlFQ0ePFht27ZV27ZtlZaWpo8//jigTmZmphwOR8AyfPjwYJ8KAJwdfL7KOz/GVN9WVTZxonWf7GFs0SKpc2fpyiul3/628mfnzmd/Xrz11lv19ddfW92MerM0ACUlJWnKlCnatGmTNm7cqKuuukojRozQtm3baqyfn5+v0aNHa/Xq1SosLJTb7dawYcO0f//+gHrDhw9XSUmJf5k3b14oTgcAmr41a6rf+fk5Y6S9eyvrwc/ON81atGih2NhYq5tRb5YGoBtuuEHXXXedunbtqgsvvFBPP/20WrdurfXr19dY/69//avuuece9enTR926ddOrr76qiooKrVy5MqCe0+lUfHy8f2nbtm0oTgcAmr6SksatZwNW3jSrqKjQ1KlT1aVLFzmdTnXs2FFPP/10DW30ady4cUpOTlaLFi2UkpKi6dOnB9TJz8/XgAED1KpVK7Vp00aXXXaZdu/eLUn67LPPdOWVVyo6OloxMTHq16+fNm7cKKnmR2D/+7//q/79+ysqKkrt27fXTTfd5N/2xhtv6JJLLlF0dLTi4+P129/+VocOHWrkK/PLwqYTtM/n04IFC1RWVqbU1NQ67fPDDz/o5MmTateuXUB5fn6+YmNj1bZtW1111VV66qmnTju4VXl5ucrLy/3rXq/3zE4CAJq6hITGrWcD9blpNnRo4/7u7OxsvfLKK3rxxRd1+eWXq6SkRF999VW1ehUVFUpKStKCBQt07rnnat26dbr77ruVkJCgW265RT/99JMyMjJ01113ad68eTpx4oQ+/vhj/1fOb7vtNvXt21czZ85URESEioqKah2E8N1339VNN92kf//3f9frr7+uEydO6L333vNvP3nypJ588kmlpKTo0KFDmjRpkjIzMwPqhISx2Oeff25atWplIiIijMvlMu+++26d9x0/frw5//zzzY8//ugvmzdvnnnnnXfM559/bvLy8sxFF11k+vfvb3766adajzN58mQjqdri8XgadG4A0OT89JMxSUnGOBzGVH52By4OhzFud2W9s8SPP/5ovvjii4DPkvqYO7fmS3XqMndu47bb6/Uap9NpXnnllWrbiouLjSSzefPmWvfPysoy//Iv/2KMMebw4cNGksnPz6+xbnR0tMnNza1x25w5c4zL5fKvp6ammttuu63O5/HJJ58YSebo0aPGGGNWr15tJJnvv/++xvqn+3t5PJ46f35b/i2wlJQUFRUVacOGDRo/frzGjh2rL7744hf3mzJliubPn6+8vDxFRUX5y0eNGqUbb7xRPXv2VEZGhpYsWaJPPvlE+fn5tR4rOztbHo/Hv+zdu7cxTg0Amp6IiMqvukvSqQPOVa1Pm8Z4QD9j1U2zL7/8UuXl5br66qvrVH/GjBnq16+fOnTooNatW+vl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eMB8+eWXZsaMGSYiIsIsXbrUqlMImfpeqxdffNEsXrzYfPPNN2bLli3m3nvvNc2aNTMffPCBVacQMuPHjzcul8vk5+ebkpIS//LDDz/46/CeVelMrpVd37MeeughU1BQYIqLi83nn39uHnroIeNwOMzy5cuNMeHzmiIABcGf//xn07FjRxMZGWkGDBhg1q9f7982ZMgQM3bs2ID6//M//2MuvPBCExkZabp3727efffdELfYOvW5VhMnTvTXjYuLM9ddd5359NNPLWh16FV9VfvUper6jB071gwZMqTaPn369DGRkZHm/PPPN3PmzAl5u61Q32v1zDPPmAsuuMBERUWZdu3amaFDh5pVq1ZZ0/gQq+k6SQp4rfCeVelMrpVd37N+//vfm06dOpnIyEjToUMHc/XVV/vDjzHh85pyGGNMcO8xAQAAhBf6AAEAANshAAEAANshAAEAANshAAEAANshAAEAANshAAEAANshAAEAANshAAEAANshAAEAANshAAGwpT/84Q+67bbbrG4GAIswFQYAW/q///s/OZ1OtWrVyuqmALAAAQgAANgOj8AA2M6uXbvkcDi0a9cuq5sCwCIEIAC289lnn6lNmzbq3Lmz1U0BYBECEADbKSoqUq9evaxuBgALEYAA2M5nn32mPn36WN0MABYiAAGwnaKiIvXu3dvqZgCwEAEIgK14vV7t2rWLO0CAzRGAANjKZ599poiICHXv3t3qpgCwEAEIgK189tln6tatm5xOp9VNAWAhBkIEAAC2wx0gAABgOwQgAABgOwQgAABgOwQgAABgOwQgAABgOwQgAABgOwQgAABgOwQgAABgOwQgAABgOwQgAABgOwQgAABgO/8PGlqQeup8Cc8AAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "plt.plot(sol_classical, \"bo\", label=\"classical\")\n",
    "plt.plot(qsol_corrected, \"ro\", label=\"HHL\")\n",
    "plt.legend()\n",
    "plt.xlabel(\"$i$\")\n",
    "plt.ylabel(\"$x_i$\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4a6fd29-f3d7-40c1-8d3c-67feedff2deb",
   "metadata": {},
   "source": [
    "**The lines below verifies that there is no functional error, which might come from changing endianness in Model or Execution.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "9ea18ab1-3b8d-4277-a98f-2cd3b210a13b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:52.770518Z",
     "iopub.status.busy": "2024-05-07T14:33:52.769290Z",
     "iopub.status.idle": "2024-05-07T14:33:52.774835Z",
     "shell.execute_reply": "2024-05-07T14:33:52.774128Z"
    }
   },
   "outputs": [],
   "source": [
    "if np.linalg.norm(sol_classical - qsol_corrected) / np.linalg.norm(sol_classical) > 0.1:\n",
    "    raise Exception(\n",
    "        \"The HHL solution is too far from the classical one, please verify your algorithm\"\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c5d5ea31-3ab2-4eb5-8522-9462e6ccfa40",
   "metadata": {
    "tags": []
   },
   "source": [
    "## 4. Generalizations\n",
    "\n",
    "The usecase treated above is a canonical one, assuming the following properties:\n",
    "1) The RHS vector $\\vec{b}$ is normalized.\n",
    "2) The matrix $A$ is an Hermitian one.\n",
    "3) The matrix $A$ is of size $2^n\\times 2^n $.\n",
    "4) The eigenvalues of $A$ are in the range $(0,1)$.\n",
    "\n",
    "However, any general problem that does not follow these conditions can be resolved as follows:\n",
    "\n",
    "1) As preprocessing, normalize $\\vec{b}$ and then return the normalization factor as a post-processing\n",
    "2) Symmetrize the problem as follows:\n",
    "$$\n",
    "\\begin{pmatrix}\n",
    "0 & A^T \\\\\n",
    "A & 0\n",
    "\\end{pmatrix}\n",
    "\\begin{pmatrix}\n",
    "\\vec{b}  \\\\\n",
    "0\n",
    "\\end{pmatrix}\n",
    "=\n",
    "\\begin{pmatrix}\n",
    "0  \\\\\n",
    "\\vec{x}\n",
    "\\end{pmatrix}.\n",
    "$$\n",
    "This increases the number of qubits by 1.\n",
    "3) Complete the matrix dimension to the closest $2^n$ with an identity matrix. The vector $\\vec{b}$ will be completed with zeros.\n",
    "$$\n",
    "\\begin{pmatrix}\n",
    "A & 0 \\\\\n",
    "0 & I\n",
    "\\end{pmatrix}\n",
    "\\begin{pmatrix}\n",
    "\\vec{b}  \\\\\n",
    "0\n",
    "\\end{pmatrix}\n",
    "=\n",
    "\\begin{pmatrix}\n",
    "\\vec{x}  \\\\\n",
    "0\n",
    "\\end{pmatrix}.\n",
    "$$\n",
    "4) If the eigenvalues of $A$ are in the range $[-w_{\\min},w_{\\max}]$ you can employ transformations to the exponentiated matrix that enters into the Hamiltonian simulation, and then undo them for extracting the results:\n",
    "$$\n",
    "\\tilde{A}=(A+w_{\\min}I)\\left(1-\\frac{1}{2^{m}}\\right)\\frac{1}{w_{\\min}+w_{\\max}}.\n",
    "$$\n",
    "The eigenvalues of this matrix lie in the interval $[0,1)$, and are related to the eigenvalues of the original matrix via\n",
    "$$\n",
    "\\lambda = (w_{\\min}+w_{\\max})\\tilde{\\lambda}\\left[1/\\left(1-\\frac{1}{2^{n_{m}}}\\right)\\right]-w_{\\min},\n",
    "$$\n",
    "with $\\tilde{\\lambda}$ being an eigenvalue of $\\tilde{A}$ resulting from the QPE algorithm. This relation between eigenvalues is then used for the expression inserted into the eigenvalue inversion, via the `AmplitudeLoading` function."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dfa04f60-9f81-49d9-860e-179169bd5cdf",
   "metadata": {},
   "source": [
    "## References\n",
    "\n",
    "<a name='HHL'>[1]</a>: [Harrow, A. W., Hassidim, A., & Lloyd, S., Quantum Algorithm for Linear Systems of Equations. Physical Review Letters 103, 150502 (2009)](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.103.150502).\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
